﻿// -----------------------------------------------------------------------
//  <copyright file="Program.cs" company="Henric Jungheim">
//  Copyright (c) 2012-2015.
//  <author>Henric Jungheim</author>
//  </copyright>
// -----------------------------------------------------------------------
// Copyright (c) 2012-2015 Henric Jungheim <software@henric.org>
// 
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using SM.Media.Pls;
using SM.Media.Utility;
using SM.Media.Web;

namespace SimplePlayer
{
    static class Program
    {
        static readonly string[] Sources =
        {
            "http://www.npr.org/streams/mp3/nprlive24.pls"
        };

        static async Task PlayAsync(SingleStreamSimulator simulator, CancellationToken cancellationToken)
        {
            var source = new Uri(Sources[0]);

            if (source.HasExtension(".pls"))
            {
                using (var client = new HttpClient())
                using (var response = await client.GetAsync(source, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false))
                {
                    response.EnsureSuccessStatusCode();

                    using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                    using (var reader = new StreamReader(stream))
                    {
                        var pls = new PlsParser(response.RequestMessage.RequestUri);

                        if (!await pls.ParseAsync(reader).ConfigureAwait(false))
                            throw new FileNotFoundException("Unable to parse PLS playlist");

                        var track = pls.Tracks.FirstOrDefault();

                        if (null == track)
                            throw new FileNotFoundException("Empty PLS playlist");

                        Uri trackUrl;
                        if (!Uri.TryCreate(pls.BaseUrl, track.File, out trackUrl))
                            throw new FileNotFoundException("Invalid URL in PLS playlist");

                        source = trackUrl;
                    }
                }
            }

            await simulator.StartAsync(source, cancellationToken).ConfigureAwait(false);
        }

        static void Main(string[] args)
        {
            TaskScheduler.UnobservedTaskException +=
                (sender, eventArgs) =>
                {
                    Console.WriteLine("*** Unobserved task exception {0}", eventArgs.Exception.Message);

                    if (Debugger.IsAttached)
                        Debugger.Break();
                };

            try
            {
                using (var simulator = new SingleStreamSimulator())
                {
                    PlayAsync(simulator, CancellationToken.None).Wait();

                    Console.WriteLine("Press <enter> to exit");

                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                if (Debugger.IsAttached)
                    Debugger.Break();
            }

            try
            {
                TaskCollector.Default.Wait();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);

                if (Debugger.IsAttached)
                    Debugger.Break();
            }
        }
    }
}

